﻿using System;
using System.Collections.Generic;
using System.Common;
using System.Linq;
using System.Text;
using System.Windows;

namespace ICodeShare.UI.Utils.Helpers
{
    public static class RectHelper
    {
       public static Rect New(Size size) {
			return new Rect(0, 0, size.Width, size.Height);
		}

       public static void SetLocation(ref Rect rect, Point location)
       {
           rect.X = location.X;
           rect.Y = location.Y;
       }
       public static void SetSize(ref Rect rect, Size size)
       {
           rect.Width = size.Width;
           rect.Height = size.Height;
       }
       public static Thickness Padding(Rect outsideRect, Rect insideRect)
       {
           Thickness result = new Thickness(0);
           result.Left = insideRect.Left - outsideRect.Left;
           result.Top = insideRect.Top - outsideRect.Top;
           result.Right = outsideRect.Right - insideRect.Right;
           result.Bottom = outsideRect.Bottom - insideRect.Bottom;
           return result;
       }
       public static void IncLeft(ref Rect rect, double value)
       {
           SetLeft(ref rect, rect.Left + value);
       }
       public static void IncTop(ref Rect rect, double value)
       {
           SetTop(ref rect, rect.Top + value);
       }
       public static void SetLeft(ref Rect rect, double left)
       {
           if (!double.IsInfinity(rect.Width))
               rect.Width = Math.Max(0, rect.Width - (left - rect.Left));
           rect.X = left;
       }
       public static void SetRight(ref Rect rect, double right)
       {
           rect.Width = Math.Max(0, right - rect.Left);
       }
       public static void SetTop(ref Rect rect, double top)
       {
           if (!double.IsInfinity(rect.Height))
               rect.Height = Math.Max(0, rect.Height - (top - rect.Top));
           rect.Y = top;
       }
       public static void SetBottom(ref Rect rect, double bottom)
       {
           rect.Height = Math.Max(0, bottom - rect.Top);
       }
       public static void Inflate(ref Rect rect, double x, double y)
       {
           rect.X -= x;
           rect.Y -= y;
           double width = rect.Width + 2 * x;
           double height = rect.Height + 2 * y;
           if (width < 0 || height < 0)
               rect = Rect.Empty;
           else
           {
               rect.Width = width;
               rect.Height = height;
           }
       }
       public static void Inflate(ref Rect rect, Side side, double value)
       {
           switch (side)
           {
               case Side.Left:
                   IncLeft(ref rect, -value);
                   return;
               case Side.Top:
                   IncTop(ref rect, -value);
                   return;
               case Side.Right:
                   rect.Width += value;
                   return;
               case Side.Bottom:
                   rect.Height += value;
                   return;
           }
       }
       public static void Offset(ref Rect rect, double x, double y)
       {
           rect.Offset(x, y);
       }
       public static void AlignHorizontally(ref Rect rect, Rect area, HorizontalAlignment alignment)
       {
           switch (alignment)
           {
               case HorizontalAlignment.Left:
                   rect.X = area.Left;
                   break;
               case HorizontalAlignment.Center:
                   rect.X = ((area.Left + area.Right - rect.Width) / 2).Round();
                   break;
               case HorizontalAlignment.Right:
                   rect.X = Math.Floor(area.Right - rect.Width);
                   break;
               case HorizontalAlignment.Stretch:
                   rect.X = area.Left;
                   rect.Width = area.Width;
                   break;
           }
       }
       public static void AlignVertically(ref Rect rect, Rect area, VerticalAlignment alignment)
       {
           switch (alignment)
           {
               case VerticalAlignment.Top:
                   rect.Y = area.Top;
                   break;
               case VerticalAlignment.Center:
                   rect.Y = ((area.Top + area.Bottom - rect.Height) / 2).Round();
                   break;
               case VerticalAlignment.Bottom:
                   rect.Y = Math.Floor(area.Bottom - rect.Height);
                   break;
               case VerticalAlignment.Stretch:
                   rect.Y = area.Top;
                   rect.Height = area.Height;
                   break;
           }
       }
       public static void Deflate(ref Rect rect, Thickness padding)
       {
           rect.X += padding.Left;
           rect.Y += padding.Top;
           rect.Width = Math.Max(0, rect.Width - (padding.Left + padding.Right));
           rect.Height = Math.Max(0, rect.Height - (padding.Top + padding.Bottom));
       }
       public static void Inflate(ref Rect rect, Thickness padding)
       {
           rect.X -= padding.Left;
           rect.Y -= padding.Top;
           rect.Width += padding.Left + padding.Right;
           rect.Height += padding.Top + padding.Bottom;
       }
#if !DXWINDOW
       public static void SnapToDevicePixels(ref Rect rect)
       {
           rect.Width = UIElementExtension.GetRoundedSize(rect.Width);
           rect.Height = UIElementExtension.GetRoundedSize(rect.Height);
       }
#endif
       public static double GetSideOffset(this Rect rect, Side side)
       {
           switch (side)
           {
               case Side.Left:
                   return rect.Left;
               case Side.Top:
                   return rect.Top;
               case Side.Right:
                   return rect.Right;
               case Side.Bottom:
                   return rect.Bottom;
               default:
                   return double.NaN;
           }
       }
       public static void Union(this Rect rect1, Rect rect2)
       {
           rect1.Union(rect2);
       }
    }
}
